/**
 * @file xbutton.h
 * @author eric
 * @brief
 * @version 0.1
 * @date 2024-09-19
 *
 * @copyright Copyright (c) 2024
 *
 */

#ifndef _XBUTTON_H_
#define _XBUTTON_H_

#include <stdint.h>
#include "dlist.h"

// According to your need to modify the constants.
#define TICKS_INTERVAL 5                         // 5ms调用间隔
#define TICKS_DEBOUNCE 3                         // 约15ms（MAX 8）
#define TICKS_SHORT    (100 / TICKS_INTERVAL)    // 100ms, 按下持续时长
#define TICKS_LONG     (1000 / TICKS_INTERVAL)   // 1s
#define TICKS_IDEL     (200 / TICKS_INTERVAL)    // 200ms，弹起释放时长

#define TICKS_HOLD_INTERVAL (50)   // 长按触发间隔，约250ms

#ifndef ACTIVE_HIGHT
#define ACTIVE_HIGHT 1
#endif

#ifndef ACTIVE_LOW
#define ACTIVE_LOW 0
#endif

// 获取按键值回调函数
typedef uint8_t (*read_key_cb)();
// 按键响应回调函数
typedef void (*event_cb)(void*);

typedef enum
{
    B_EVENT_NONE = 0,
    B_EVENT_DOWN,
    B_EVENT_UP,
    B_EVENT_REPEAT,
    B_EVENT_CLICK,
    B_EVENT_DOUBLE_CLICK,
    B_EVENT_PRESS_START,
    B_EVENT_PRESS_HOLD,
    B_EVENT_MAX
} button_event_t;

typedef struct button_node
{
    uint16_t ticks;
    uint8_t  repeat;
    uint8_t  event;
    uint8_t  state;
    uint8_t  debounce_cnt;
    uint8_t  active_level;   // 按键有效值
    uint8_t  level;          // 按键值

    read_key_cb read_key;   // 读取按键值
    event_cb    cb[B_EVENT_MAX];

    struct list_head list;
} button_t;

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief 初始化按键
 *
 * @param handle 按键主体
 * @param read_key 读取按键值回调
 * @param active_level 按键有效状态 ACTIVE_HIGHT or ACTIVE_LOW
 */
void button_init(button_t* handle, read_key_cb read_key, uint8_t active_level);

/**
 * @brief 绑定按键事件
 *
 * @param handle 按键主体
 * @param event 事件类型
 * @param cb 回调函数
 */
void button_bind(button_t* handle, button_event_t event, event_cb cb);

/**
 * @brief 获取按键事件
 *
 * @param handle 按键主体
 * @return button_event_t
 */
button_event_t button_get_event(button_t* handle);

/**
 * @brief 获取按键是否被按下
 *
 * @param handle 按键主体
 * @return uint8_t
 */
uint8_t button_is_active(button_t* handle);

/**
 * @brief 开启一个按键
 *
 * @param handle 按键主体
 * @return int 0 or -1
 */
int button_start(button_t* handle);

/**
 * @brief 停止一个按键
 *
 * @param handle
 */
int button_stop(button_t* handle);

/**
 * @brief 按键循环任务，5ms被调用一次
 *
 */
void button_loops(void);

#ifdef __cplusplus
}
#endif

#endif
